package com.top.art.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.top.art.bo.StudioBO;
import com.top.art.constants.CommonErrorCodeEnum;
import com.top.art.constants.Status;
import com.top.art.entity.Address;
import com.top.art.entity.ExamineeInfo;
import com.top.art.entity.StudioInfo;
import com.top.art.exception.ArtException;
import com.top.art.mapper.StudioInfoMapper;
import com.top.art.service.IAddressService;
import com.top.art.service.IExamineeInfoService;
import com.top.art.service.IStudioInfoService;
import com.top.art.vo.ProvinceVO;
import com.top.art.vo.StudioVo;
import com.top.art.vo.WorksStatisticsVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.Clock;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 画室信息表 服务实现类
 * </p>
 *
 * @author hjh
 * @since 2020-10-05
 */
@Slf4j
@Service
public class StudioInfoServiceImpl extends ServiceImpl<StudioInfoMapper, StudioInfo> implements IStudioInfoService {

    @Autowired
    private IExamineeInfoService examineeInfoService;

    @Autowired
    private IAddressService iAddressService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveData(StudioInfo studioInfo, MultipartFile examineeFile) throws IOException {
        if (null != studioInfo) {
            List<ExamineeInfo> examineeInfos = new ArrayList<>();
            if (examineeFile != null && !examineeFile.isEmpty()) {
                examineeInfos = readExamineeInfo(examineeFile);
                if (!examineeInfos.isEmpty()) {
                    for (ExamineeInfo examineeInfo : examineeInfos) {
                        if (examineeInfo.getIdentificationNumber().length() != 18) {
                            throw new ArtException(CommonErrorCodeEnum.IDENTIFICATIONNUMBER_ERROR.getCode(),
                                    CommonErrorCodeEnum.IDENTIFICATIONNUMBER_ERROR.getMessage());
                        }
                    }
                }
            }
            String studioCode;
            // 根据名称查询是否已经存在画室
            StudioInfo entity = this.getOne(new QueryWrapper<StudioInfo>().lambda().eq(StringUtils.isNotBlank(studioInfo.getStudioName()), StudioInfo::getStudioName, studioInfo.getStudioName())
                    .eq(StudioInfo::getActivityStatus, Status.VALID));
            if (entity == null) {
                List<StudioInfo> list = this.list(new QueryWrapper<StudioInfo>().orderByDesc("id"));
                if (list != null && !list.isEmpty()) {
                    studioCode = String.valueOf(Integer.parseInt(list.get(0).getStudioCode()) + 1);
                } else {
                    studioCode = "1001";
                }
                studioInfo.setStudioCode(studioCode);
                studioInfo.setExamineeCount(examineeInfos.size());
                studioInfo.setActivityStatus(1);
                studioInfo.setCreateTime(LocalDateTime.now(Clock.system(ZoneId.of("Asia/Shanghai"))));
                studioInfo.setLastUpdateTime(LocalDateTime.now(Clock.system(ZoneId.of("Asia/Shanghai"))));
                this.baseMapper.insert(studioInfo);
            } else {
                throw new ArtException(500, "画室已存在");
            }
            if (examineeInfos != null && !examineeInfos.isEmpty()) {
                List<String> ids = examineeInfos.stream().map(ExamineeInfo::getIdentificationNumber).collect(Collectors.toList());
                List<ExamineeInfo> temp = examineeInfoService.list(new QueryWrapper<ExamineeInfo>().in("identification_number", ids));
                if (!temp.isEmpty()) {
                    throw new ArtException(500, "文件错误，请确认身份证号唯一和格式正确");
                }
                List<Address> addresses = iAddressService.list();
                Map<String, String> addressesMap = addresses.stream().collect(Collectors.toMap(Address::getAreaName, Address::getAreaCode));
                for (ExamineeInfo i : examineeInfos) {
                    i.setProvinceCode(addressesMap.getOrDefault(i.getProvince(), null));
                    i.setActivityStatus(1);
                    i.setStudioCode(studioCode);
                    i.setStudioName(studioInfo.getStudioName());
                    i.setCreateTime(LocalDateTime.now(Clock.system(ZoneId.of("Asia/Shanghai"))));
                    i.setLastUpdateTime(LocalDateTime.now(Clock.system(ZoneId.of("Asia/Shanghai"))));
                }
                examineeInfoService.saveBatch(examineeInfos);
            }
        }
        return true;
    }

    private List<ExamineeInfo> readExamineeInfo(MultipartFile examineeFile) throws IOException {
        List<ExamineeInfo> examineeInfos;
        if (examineeFile != null && !examineeFile.isEmpty()) {
            File file = multipartfileToFile(examineeFile);
            ExamineeExcelReadListener listener = new ExamineeExcelReadListener();
            EasyExcel.read(examineeFile.getInputStream(), ExamineeInfo.class, listener).sheet(0).doReadSync();
            FileUtils.deleteQuietly(file);
            examineeInfos = listener.getDatas();
        } else {
            examineeInfos = new ArrayList<>();
        }
        return examineeInfos;
    }

    @Override
    public boolean update(StudioInfo studioInfo) {
        studioInfo.setLastUpdateTime(LocalDateTime.now(Clock.system(ZoneId.of("Asia/Shanghai"))));
        return this.updateById(studioInfo);
    }

    @Override
    public IPage<StudioInfo> page(StudioBO bo) {
        return page(new Page<>(bo.getCurrent(), bo.getSize()), Wrappers.<StudioInfo>lambdaQuery()
                .like(StringUtils.isNotBlank(bo.getStuName()), StudioInfo::getStudioName, bo.getStuName())
                .eq(bo.getId() != null, StudioInfo::getId, bo.getId())
                .eq(StringUtils.isNotBlank(bo.getStudioCode()), StudioInfo::getStudioCode, bo.getStudioCode())
                .eq(StringUtils.isNotBlank(bo.getStudioAreaCode()), StudioInfo::getStudioAreaCode, bo.getStudioAreaCode())
                .eq(StringUtils.isNotBlank(bo.getStudioName()), StudioInfo::getStudioName, bo.getStudioName())
        );
    }

    @Override
    public boolean operationActivity(StudioBO bo) {
        try {
            return this.update(Wrappers.<StudioInfo>lambdaUpdate().eq(StudioInfo::getStudioCode, bo.getStudioCode()).set(StudioInfo::getActivityStatus, bo.getActivityStatus()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public StudioVo queryOrupdateByCode(StudioBO bo) {
        LambdaQueryWrapper<StudioInfo> queryWrapper = Wrappers.<StudioInfo>lambdaQuery().eq(StudioInfo::getStudioCode, bo.getStudioCode());
        StudioInfo info = queryWrapper.getEntity();
        if (null == info) {
            this.save(info);
        }
        StudioVo vo = new StudioVo();
        BeanUtils.copyProperties(info, vo);
        return vo;
    }

    @Override
    public List<WorksStatisticsVO> queryCount(String studioCode) {
        return baseMapper.queryCount(studioCode);
    }

    @Override
    public List<ProvinceVO> queryProvince() {
        return baseMapper.queryProvince();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteStudio(Integer id) {
        try {
            Map<String, Object> columnMap = new HashMap<>();
            columnMap.put("studio_code",this.getById(id).getStudioCode());
            examineeInfoService.removeByMap(columnMap);
            return this.removeById(id);
        } catch (Exception e) {
            throw new ArtException(5300, "数据问题，请联系管理员删除!");
        }
    }

    @Override
    public StudioVo countExaminationInfo(String provinceCode) {
        StudioVo vo = examineeInfoService.countExaminationInfo(provinceCode);
        List<StudioInfo> list = this.list(Wrappers.<StudioInfo>lambdaQuery().orderByDesc(StudioInfo::getCreateTime));
        if(!list.isEmpty()){
            vo.setMaxExamCode(list.get(0).getStudioCode());
        }
        return vo;
    }

    public File multipartfileToFile(MultipartFile multipartFile) {
        File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
        try {
            FileUtils.copyInputStreamToFile(multipartFile.getInputStream(), file);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


}
